package org.dromara.ai.config;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * AI配置管理服务
 * 支持动态配置和热更新
 *
 * @author RuoYi
 * @since 2024-01-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AiConfigurationManager {

    private final ApplicationEventPublisher eventPublisher;
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
    
    // 配置存储
    private final Map<String, AiConfiguration> configurations = new ConcurrentHashMap<>();
    
    // 配置监听器
    private final Map<String, Consumer<AiConfiguration>> configListeners = new ConcurrentHashMap<>();
    
    // 配置版本
    private final Map<String, Long> configVersions = new ConcurrentHashMap<>();
    
    // 配置历史
    private final Map<String, Map<Long, AiConfiguration>> configHistory = new ConcurrentHashMap<>();
    
    /**
     * AI配置类
     */
    public static class AiConfiguration {
        private String key;
        private Object value;
        private String description;
        private ConfigType type;
        private boolean hotReloadable;
        private LocalDateTime createTime;
        private LocalDateTime updateTime;
        private String updatedBy;
        private Map<String, Object> metadata;
        
        // Getters and Setters
        public String getKey() { return key; }
        public AiConfiguration setKey(String key) { this.key = key; return this; }
        
        public Object getValue() { return value; }
        public AiConfiguration setValue(Object value) { this.value = value; return this; }
        
        public String getDescription() { return description; }
        public AiConfiguration setDescription(String description) { this.description = description; return this; }
        
        public ConfigType getType() { return type; }
        public AiConfiguration setType(ConfigType type) { this.type = type; return this; }
        
        public boolean isHotReloadable() { return hotReloadable; }
        public AiConfiguration setHotReloadable(boolean hotReloadable) { this.hotReloadable = hotReloadable; return this; }
        
        public LocalDateTime getCreateTime() { return createTime; }
        public AiConfiguration setCreateTime(LocalDateTime createTime) { this.createTime = createTime; return this; }
        
        public LocalDateTime getUpdateTime() { return updateTime; }
        public AiConfiguration setUpdateTime(LocalDateTime updateTime) { this.updateTime = updateTime; return this; }
        
        public String getUpdatedBy() { return updatedBy; }
        public AiConfiguration setUpdatedBy(String updatedBy) { this.updatedBy = updatedBy; return this; }
        
        public Map<String, Object> getMetadata() { return metadata; }
        public AiConfiguration setMetadata(Map<String, Object> metadata) { this.metadata = metadata; return this; }
    }
    
    /**
     * 配置类型枚举
     */
    public enum ConfigType {
        PROVIDER_CONFIG,    // Provider配置
        MODEL_CONFIG,       // 模型配置
        SECURITY_CONFIG,    // 安全配置
        MONITOR_CONFIG,     // 监控配置
        SYSTEM_CONFIG       // 系统配置
    }
    
    /**
     * 配置变更事件
     */
    public static class ConfigChangeEvent {
        private String key;
        private Object oldValue;
        private Object newValue;
        private ConfigType type;
        private LocalDateTime changeTime;
        private String changedBy;
        
        public ConfigChangeEvent(String key, Object oldValue, Object newValue, ConfigType type, String changedBy) {
            this.key = key;
            this.oldValue = oldValue;
            this.newValue = newValue;
            this.type = type;
            this.changeTime = LocalDateTime.now();
            this.changedBy = changedBy;
        }
        
        // Getters
        public String getKey() { return key; }
        public Object getOldValue() { return oldValue; }
        public Object getNewValue() { return newValue; }
        public ConfigType getType() { return type; }
        public LocalDateTime getChangeTime() { return changeTime; }
        public String getChangedBy() { return changedBy; }
    }
    
    /**
     * 应用启动后初始化
     */
    @EventListener(ApplicationReadyEvent.class)
    public void initialize() {
        log.info("初始化AI配置管理器");
        
        // 加载默认配置
        loadDefaultConfigurations();
        
        // 启动配置监控
        startConfigMonitoring();
        
        log.info("AI配置管理器初始化完成，已加载{}个配置项", configurations.size());
    }
    
    /**
     * 获取配置
     *
     * @param key 配置键
     * @return 配置值
     */
    @SuppressWarnings("unchecked")
    public <T> T getConfig(String key) {
        AiConfiguration config = configurations.get(key);
        return config != null ? (T) config.getValue() : null;
    }
    
    /**
     * 获取配置（带默认值）
     *
     * @param key 配置键
     * @param defaultValue 默认值
     * @return 配置值
     */
    @SuppressWarnings("unchecked")
    public <T> T getConfig(String key, T defaultValue) {
        AiConfiguration config = configurations.get(key);
        return config != null ? (T) config.getValue() : defaultValue;
    }
    
    /**
     * 设置配置
     *
     * @param key 配置键
     * @param value 配置值
     * @param type 配置类型
     * @param updatedBy 更新者
     */
    public void setConfig(String key, Object value, ConfigType type, String updatedBy) {
        setConfig(key, value, type, true, null, updatedBy);
    }
    
    /**
     * 设置配置（完整参数）
     *
     * @param key 配置键
     * @param value 配置值
     * @param type 配置类型
     * @param hotReloadable 是否支持热更新
     * @param description 配置描述
     * @param updatedBy 更新者
     */
    public void setConfig(String key, Object value, ConfigType type, boolean hotReloadable, 
                         String description, String updatedBy) {
        AiConfiguration oldConfig = configurations.get(key);
        Object oldValue = oldConfig != null ? oldConfig.getValue() : null;
        
        AiConfiguration newConfig = new AiConfiguration()
            .setKey(key)
            .setValue(value)
            .setType(type)
            .setHotReloadable(hotReloadable)
            .setDescription(description)
            .setUpdatedBy(updatedBy)
            .setUpdateTime(LocalDateTime.now());
        
        if (oldConfig == null) {
            newConfig.setCreateTime(LocalDateTime.now());
        } else {
            newConfig.setCreateTime(oldConfig.getCreateTime());
        }
        
        configurations.put(key, newConfig);
        
        // 更新版本
        long newVersion = configVersions.getOrDefault(key, 0L) + 1;
        configVersions.put(key, newVersion);
        
        // 保存历史
        configHistory.computeIfAbsent(key, k -> new ConcurrentHashMap<>())
            .put(newVersion, newConfig);
        
        // 触发配置变更事件
        ConfigChangeEvent event = new ConfigChangeEvent(key, oldValue, value, type, updatedBy);
        eventPublisher.publishEvent(event);
        
        // 通知监听器
        Consumer<AiConfiguration> listener = configListeners.get(key);
        if (listener != null && hotReloadable) {
            try {
                listener.accept(newConfig);
                log.info("配置热更新成功: {} = {}", key, value);
            } catch (Exception e) {
                log.error("配置热更新失败: {}", key, e);
            }
        }
        
        log.info("配置已更新: {} = {} (版本: {})", key, value, newVersion);
    }
    
    /**
     * 删除配置
     *
     * @param key 配置键
     * @param updatedBy 操作者
     */
    public void removeConfig(String key, String updatedBy) {
        AiConfiguration config = configurations.remove(key);
        if (config != null) {
            // 触发配置变更事件
            ConfigChangeEvent event = new ConfigChangeEvent(key, config.getValue(), null, config.getType(), updatedBy);
            eventPublisher.publishEvent(event);
            
            log.info("配置已删除: {}", key);
        }
    }
    
    /**
     * 注册配置监听器
     *
     * @param key 配置键
     * @param listener 监听器
     */
    public void addConfigListener(String key, Consumer<AiConfiguration> listener) {
        configListeners.put(key, listener);
        log.debug("已注册配置监听器: {}", key);
    }
    
    /**
     * 移除配置监听器
     *
     * @param key 配置键
     */
    public void removeConfigListener(String key) {
        configListeners.remove(key);
        log.debug("已移除配置监听器: {}", key);
    }
    
    /**
     * 获取所有配置
     *
     * @return 配置映射
     */
    public Map<String, AiConfiguration> getAllConfigurations() {
        return new ConcurrentHashMap<>(configurations);
    }
    
    /**
     * 获取指定类型的配置
     *
     * @param type 配置类型
     * @return 配置映射
     */
    public Map<String, AiConfiguration> getConfigurationsByType(ConfigType type) {
        Map<String, AiConfiguration> result = new ConcurrentHashMap<>();
        configurations.forEach((key, config) -> {
            if (config.getType() == type) {
                result.put(key, config);
            }
        });
        return result;
    }
    
    /**
     * 获取配置历史
     *
     * @param key 配置键
     * @return 配置历史
     */
    public Map<Long, AiConfiguration> getConfigHistory(String key) {
        return configHistory.getOrDefault(key, new ConcurrentHashMap<>());
    }
    
    /**
     * 回滚配置到指定版本
     *
     * @param key 配置键
     * @param version 版本号
     * @param updatedBy 操作者
     */
    public void rollbackConfig(String key, long version, String updatedBy) {
        Map<Long, AiConfiguration> history = configHistory.get(key);
        if (history == null || !history.containsKey(version)) {
            throw new IllegalArgumentException("配置版本不存在: " + key + " v" + version);
        }
        
        AiConfiguration historicalConfig = history.get(version);
        setConfig(key, historicalConfig.getValue(), historicalConfig.getType(), 
                 historicalConfig.isHotReloadable(), historicalConfig.getDescription(), updatedBy);
        
        log.info("配置已回滚: {} 到版本 {}", key, version);
    }
    
    /**
     * 重新加载所有配置
     */
    public void reloadAllConfigurations() {
        log.info("开始重新加载所有配置");
        
        configurations.forEach((key, config) -> {
            if (config.isHotReloadable()) {
                Consumer<AiConfiguration> listener = configListeners.get(key);
                if (listener != null) {
                    try {
                        listener.accept(config);
                        log.debug("配置重新加载成功: {}", key);
                    } catch (Exception e) {
                        log.error("配置重新加载失败: {}", key, e);
                    }
                }
            }
        });
        
        log.info("所有配置重新加载完成");
    }
    
    /**
     * 加载默认配置
     */
    private void loadDefaultConfigurations() {
        // Provider配置
        setConfig("ai.provider.openai.enabled", true, ConfigType.PROVIDER_CONFIG, true, 
                 "OpenAI Provider启用状态", "system");
        setConfig("ai.provider.openai.timeout", 30000, ConfigType.PROVIDER_CONFIG, true, 
                 "OpenAI Provider超时时间(ms)", "system");
        setConfig("ai.provider.openai.retry.max", 3, ConfigType.PROVIDER_CONFIG, true, 
                 "OpenAI Provider最大重试次数", "system");
        
        // 模型配置
        setConfig("ai.model.default", "gpt-3.5-turbo", ConfigType.MODEL_CONFIG, true, 
                 "默认AI模型", "system");
        setConfig("ai.model.temperature.default", 0.7, ConfigType.MODEL_CONFIG, true, 
                 "默认温度参数", "system");
        setConfig("ai.model.max_tokens.default", 2048, ConfigType.MODEL_CONFIG, true, 
                 "默认最大token数", "system");
        
        // 安全配置
        setConfig("ai.security.content_filter.enabled", true, ConfigType.SECURITY_CONFIG, true, 
                 "内容过滤启用状态", "system");
        setConfig("ai.security.rate_limit.enabled", true, ConfigType.SECURITY_CONFIG, true, 
                 "速率限制启用状态", "system");
        setConfig("ai.security.rate_limit.requests_per_minute", 60, ConfigType.SECURITY_CONFIG, true, 
                 "每分钟请求限制", "system");
        
        // 监控配置
        setConfig("ai.monitor.enabled", true, ConfigType.MONITOR_CONFIG, true, 
                 "监控启用状态", "system");
        setConfig("ai.monitor.metrics.retention_days", 30, ConfigType.MONITOR_CONFIG, true, 
                 "监控数据保留天数", "system");
        setConfig("ai.monitor.health_check.interval", 60, ConfigType.MONITOR_CONFIG, true, 
                 "健康检查间隔(秒)", "system");
        
        // 系统配置
        setConfig("ai.system.thread_pool.core_size", 10, ConfigType.SYSTEM_CONFIG, true, 
                 "线程池核心大小", "system");
        setConfig("ai.system.thread_pool.max_size", 50, ConfigType.SYSTEM_CONFIG, true, 
                 "线程池最大大小", "system");
        setConfig("ai.system.cache.enabled", true, ConfigType.SYSTEM_CONFIG, true, 
                 "缓存启用状态", "system");
    }
    
    /**
     * 启动配置监控
     */
    private void startConfigMonitoring() {
        // 定期检查配置变更
        scheduler.scheduleWithFixedDelay(() -> {
            try {
                // 这里可以实现从外部数据源检查配置变更
                // 例如数据库、配置中心等
                log.debug("配置监控检查完成");
            } catch (Exception e) {
                log.error("配置监控检查失败", e);
            }
        }, 30, 30, TimeUnit.SECONDS);
        
        // 定期清理历史配置
        scheduler.scheduleWithFixedDelay(() -> {
            try {
                cleanupConfigHistory();
            } catch (Exception e) {
                log.error("配置历史清理失败", e);
            }
        }, 1, 24, TimeUnit.HOURS);
    }
    
    /**
     * 清理配置历史
     */
    private void cleanupConfigHistory() {
        int maxHistoryVersions = getConfig("ai.config.history.max_versions", 10);
        
        configHistory.forEach((key, history) -> {
            if (history.size() > maxHistoryVersions) {
                // 保留最新的版本
                history.entrySet().stream()
                    .sorted(Map.Entry.<Long, AiConfiguration>comparingByKey().reversed())
                    .skip(maxHistoryVersions)
                    .map(Map.Entry::getKey)
                    .forEach(history::remove);
            }
        });
        
        log.debug("配置历史清理完成");
    }
    
    /**
     * 销毁资源
     */
    public void destroy() {
        if (scheduler != null && !scheduler.isShutdown()) {
            scheduler.shutdown();
            try {
                if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
                    scheduler.shutdownNow();
                }
            } catch (InterruptedException e) {
                scheduler.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
        log.info("AI配置管理器已销毁");
    }
}